<?php

namespace app\api\controller\xmwechat;

use app\admin\model\Order;
use app\admin\model\User;
use app\api\model\Reward;
use app\common\controller\Frontend;
use app\common\library\xmwechat\payment\PayService;
use app\common\model\Player;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\RuntimeException;
use EasyWeChat\Pay\Application;
use EasyWeChat\Pay\Message;
use think\facade\Db;
use think\facade\Log;
use think\Model;
use think\Request;
use Overtrue\EasySms\EasySms;
use app\common\model\SmsTemplate;
use app\admin\model\broker\Application as BrokerApplication;
use app\admin\model\broker\fen\Log as BrokerFenLog;
use app\admin\model\alliance\Wallet;
use app\admin\model\ad\Put;
use app\api\service\QueueOrder;
use app\common\model\GoodsOrder as GoodsOrderModel;
use app\common\model\Goods AS GoodsModel;
use GuzzleHttp\Client;
use ba\Exception;
use app\api\service\SendMsg;
class Payment extends Frontend
{
    // 数组中的 pay 请在调试完成后删除，支付接口需要登录
    protected array $noNeedLogin = ['pay', 'notify','notifybroker','notifyput','notifywx','test','notifywmb','notifyvip'];

    protected array $wechatPayConfig;

    public function initialize(): void
    {
        parent::initialize();
        $config                = config('xmwechat');
        $this->wechatPayConfig = $config['payment'];
    }

    /**
     * 微信公众号、小程序支付示例
     * 支付接口是需要登录的，测试结束后，请在最上方$noNeedLogin数组中去掉 pay
     * @param Request $request
     * @return void
     * @throws \Exception
     * @author jsjxsz <QQ:1365962177>
     */
    public function pay(Request $request): void
    {
        if ($request->isPost()) {
            // order_no：订单号 body：描述 pay_price：支付金额 openid：用户openid  transaction_no:交易号
            $params = $request->only(['order_no', 'body', 'pay_price', 'openid', 'transaction_no']);
            // miniProgram: 小程序支付； offiAccount： 公众号支付
            $params['pay_type'] = 'miniProgram';
            $result = PayService::getInstance()->pay($params);
            if ($result !== false) {
                $this->success('success', $result);
            } else {
                $this->error('error');
            }
        }
    }

    /**
     * 微信公众号、小程序支付回调
     * 注意仔细看下面的注释内容
     * @author jsjxsz <QQ:1365962177>
     */
    public function notify()
    {
        try {
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                file_put_contents('pay.text',$message . PHP_EOL, FILE_APPEND);
                $noyifyData     = json_decode($message, true);
                $pay_time       = strtotime($noyifyData['success_time']);
                $time           = time();
                $order_no       = $noyifyData['out_trade_no'];
                $transaction_id = $noyifyData['transaction_id'];
                $amount         = $noyifyData['amount']['payer_total'] / 100;//单位分


                /**
                 * 这里写你自己的逻辑 start
                 */
                // 这里查询你自己的数据表！！！
                $orderModel = new Order();
                $order = $orderModel->where('order_no', $order_no)->find();
                if (!$order || $order['status'] == 20) {
                    // 如果订单不存在 或者 订单已经支付过了
                    // 告诉微信，我已经处理完了，订单没找到，别再通知我了
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }

                // return_code 表示通信状态，不代表支付状态
                if ($noyifyData['trade_state'] === 'SUCCESS') {
                    $order->transaction_no = $transaction_id;
                    $order->pay_amount = $amount;
                    $order->pay_time = $pay_time;
                    $order->status = 20;
                    $order->update_time = $time;
                    $order->save();
                    if ($order->order_type == 'reward'){
                        $user_id = (new Player())->where('id',$order->player_id)->value('user_id');
                        $user = (new User())->find($user_id);
                        $user->money = $user->money + $order->pay_amount;
                        $user->save();
                        $reward = (new Reward())->where('order_id', $order->id)->find();
                        $reward->status = 20;
                        $reward->save();
                    }else{
                        //获取支付人信息
                        $pidInfo =(new User())->find($order->user_id);

                        //存在上级用户
                        if($pidInfo&&$pidInfo->pid>0){
                            $config = Db::name('config')->field('name,value')->where('name','commission_rate')->value('value');
                            $commission_rate =$config/100;
                            $amount =bcmul($commission_rate,$order->pay_amount,2);
                            //获得佣金
                            $data =[
                                'order_id'=>$order->id,
                                'createtime'=>time(),
                                'user_id'=>$pidInfo->pid,
                                'amount'=>$amount,
                                'commission_rate'=>$config.'%',
                            ];
                            Db::name('commission_log')->insert($data);
                        }

                    }

                    //获取支付人信息
                    $pay_user_info =(new User())->find($order->user_id);

                    //增加总消费
                    $pay_user_info->total_money +=$order->pay_amount;
                    $pay_user_info->save();


                    //短信推送达人
                    $user_name =(new User())->find($order->user_id)['nickname'];
                    $mobile = (new Player())->where('id',$order->player_id)->value('mobile');
                    $config  = config('sms');
                    $orderInfo =':'.$user_name;
                    $easySms = new EasySms($config);
                    $smsModel = new SmsTemplate();
                    $template_code = $smsModel->where('code','order_mobile')->value('template');
                    $res     = $easySms->send($mobile, [
                        'template' => $template_code,
                        'data' => [
                            $orderInfo,
                        ],
                    ]);

                    file_put_contents('kkk.txt',$res . PHP_EOL, FILE_APPEND);

                    // 支付成功
                    // 写你自己的逻辑

                } else if ($message['result_code'] === 'FAIL') {
                    // 支付失败
                    // 写你自己的逻辑
                }
                /**
                 * 这里写你自己的逻辑 end
                 */

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
 /**
     * 微信公众号、小程序支付回调
     * 注意仔细看下面的注释内容
     * @author jsjxsz <QQ:1365962177>
     */
    public function notifybroker()
    {
          Log::info('代理回调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                file_put_contents('pay.text',$message . PHP_EOL, FILE_APPEND);
                $noyifyData     = json_decode($message, true);
                $pay_time       = strtotime($noyifyData['success_time']);
                $time           = time();
                $order_no       = $noyifyData['out_trade_no'];
                $transaction_id = $noyifyData['transaction_id'];
                $amount         = $noyifyData['amount']['payer_total'] / 100;//单位分
                /**
                 * 这里写你自己的逻辑 start
                 */
                // 这里查询你自己的数据表！！！
                $orderModel =  new BrokerApplication();
                $order = $orderModel->where('order_no', $order_no)->find();
                 Log::info('代理回调来了2' . json_encode($order,JSON_UNESCAPED_UNICODE));
                if (!$order || $order['paid'] == 1) {
                    // 如果订单不存在 或者 订单已经支付过了
                    // 告诉微信，我已经处理完了，订单没找到，别再通知我了
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                // return_code 表示通信状态，不代表支付状态
                if ($noyifyData['trade_state'] === 'SUCCESS') {
                    $order->order_pay_no = $transaction_id;
                    $order->pay_time = $pay_time;
                    $order->paid = 1;
                    $order->save();
                    $pidInfo =(new User())->find($order->user_id);
                    //存在上级用户
                    if($pidInfo && ($pidInfo->pid)>0){
                       $res =  BrokerFenLog::broker_2($pidInfo->pid,$order_no,$amount,'broker_2');
                       Log::info('代理回调来了4'.$res );
                    }
                } else if ($message['result_code'] === 'FAIL') {
                    // 支付失败
                    // 写你自己的逻辑
                }
                /**
                 * 这里写你自己的逻辑 end
                 */

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
    /**
     * 退款申请（退款状态需在退款回调中获取）
     * @author jsjxsz <QQ:1365962177>
     * out_trade_no 原支付交易对应的商户订单号
     * out_refund_no 商户退款单号，商户系统内部的退款单号，退款时生成，唯一
     * reason 退款原因
     * refund_price 退款金额
     * pay_price 原交易金额
     */
    public function refunds($param)
    {
        //$params = $request->only(['pay_price', 'refund_price', 'out_trade_no','out_refund_no','reason']);
        $result = PayService::getInstance()->refunds($param);
        if ($result !== false) {
            return $result;
        } else {
            return false;
        }

    }


    //广告投流支付通知
    public function notifyput()
    {
        Log::info('广告支付调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                file_put_contents('pay.text',$message . PHP_EOL, FILE_APPEND);
                $noyifyData     = json_decode($message, true);
                $pay_time       = strtotime($noyifyData['success_time']);
                $order_no       = $noyifyData['out_trade_no'];
                $transaction_id = $noyifyData['transaction_id'];
                $amount         = $noyifyData['amount']['payer_total'] / 100;//单位分
                /**
                 * 这里写你自己的逻辑 start
                 */
                // 这里查询你自己的数据表！！！
                $orderModel =  new Put();
                $order = $orderModel->where('order_no', $order_no)->find();
                Log::info('广告支付调来了2' . json_encode($order,JSON_UNESCAPED_UNICODE));
                if (!$order || $order['status'] == 1) {
                    // 如果订单不存在 或者 订单已经支付过了
                    // 告诉微信，我已经处理完了，订单没找到，别再通知我了
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                // return_code 表示通信状态，不代表支付状态
                if ($noyifyData['trade_state'] === 'SUCCESS') {

                    $ad_package =Db::name('ad_package')->where('id',$order['package_id'])->find();

                    $order->order_pay_no = $transaction_id;
                    $order->pay_time = $pay_time;
                    $order->end_time = time() +$ad_package['days']*86400 ;
                    $order->status = 1;
                    $order->save();

                } else if ($message['result_code'] === 'FAIL') {
                    // 支付失败
                    // 写你自己的逻辑
                }
                /**
                 * 这里写你自己的逻辑 end
                 */

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
    
    
     //微信支付通知
    public function notifywx()
    {
        Log::info('微信支付调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                $notifyData   = json_decode($message, true);
                $success_time = strtotime($notifyData['success_time']);
                $out_trade_no = $notifyData['out_trade_no'];

                Log::info('微信支付回调来了' . json_encode($notifyData,JSON_UNESCAPED_UNICODE));

                // 查询订单
                $order = GoodsOrderModel::where('order_no', $out_trade_no)->find();
                if (!$order || $order['status'] == 2 || $order['status']==3) {
                    Log::info('订单不存在或者已经支付了');
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                
                elseif($notifyData['trade_state'] === 'SUCCESS'){
                    GoodsModel::where("id",$order->goods_id)->inc('sales',1)->update();
                    if($order->order_type == 2){
                        $order->out_trade_no = $notifyData['transaction_id'];
                        $order->pay_time = $success_time;
                        // $order->status = 3;
                        $order->save();
                        $model = new \app\admin\model\goods\Order();
                        $model->orderSuccess($order->id);
                       
                    } elseif ($order->order_type == 1){
                        $order->out_trade_no = $notifyData['transaction_id'];
                        $order->pay_time = $success_time;
                        $order->status = 2;
                        $order->save();
                    } elseif ($order->order_type == 3){
                        $order->out_trade_no = $notifyData['transaction_id'];
                        $order->pay_time = $success_time;
                        // $order->status = 3;
                        $order->save();
                        $model = new \app\admin\model\goods\Order();
                        $model->orderSuccess($order->id);
                        $app = new Feie();
                        $app->printMsg($order);
                    }
                    //订单排队
                    QueueOrder::addQueueOrder($order);
                    //音响播报到账
                    $sn = Db::name('store_pay')->where('store_id',  $order->store_id)->find()['sn'];
                    if(!empty($sn)){
                        SendMsg::send($out_trade_no,$order->goods_prices,$sn);
                    }

                    //获取商家类型
                    $Alliance = new \app\api\model\Alliance();
                    $store_type =$Alliance::where('id',$order->store_id)->value('type');
                    Log::info('商家类型'.$store_type);
                    
                    $Walletmodel  = new Wallet(); 
                    $Walletmodel->Commission($order);
                    
                    $userModel = new \app\common\model\User();
                    $userModel->checkPid($order->user_id);
                }

                elseif ($message['result_code'] === 'FAIL') {
                    // 支付失败逻辑
                    return ['code' => 'ERROR', 'message' => '支付失败'];
                }

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
    
    
   //余额充值支付通知
    public function notifyrecharge()
    {
        Log::info('余额充值支付调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                $notifyData   = json_decode($message, true);
                $success_time = strtotime($notifyData['success_time']);
                $out_trade_no = $notifyData['out_trade_no'];
                 
                Log::info('余额充值支付回调来了' . json_encode($notifyData,JSON_UNESCAPED_UNICODE));
                $data = explode('S',$out_trade_no);
                // 查询订单
                $log = \app\admin\model\point\Userlog();
                $order = $log->where('order_id', $out_trade_no)->find();
                if ($order) {
                    Log::info('订单已经支付了');
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                
                elseif($notifyData['trade_state'] === 'SUCCESS'){
                    $res = $log->change($data[0],3,($data[1]/100),$out_trade_no,'','',2);
                    Log::info('余额充值' . json_encode($res,320));
                }

                elseif ($message['result_code'] === 'FAIL') {
                    // 支付失败逻辑
                    return ['code' => 'ERROR', 'message' => '支付失败'];
                }

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
    
    public function test(){
    
        // $Walletmodel  = new Wallet(); 
        // $order = GoodsOrderModel::where('order_no', 'SP202410290957112506614')->find();
        // QueueOrder::addQueueOrder($order);
        // dump($res);die();
         $GoodsOrderModel =  new \app\common\model\WmbOrder();
         $res = $GoodsOrderModel->deliverCreate('WMB2024112104581833532970');
         dump($res);die();
    }
    
    
    //聚合外卖支付通知
    public function notifywmb()
    {
        Log::info('聚合外卖支付调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                $notifyData   = json_decode($message, true);
                $success_time = strtotime($notifyData['success_time']);
                $out_trade_no = $notifyData['out_trade_no'];

                Log::info('聚合外卖支付回调来了' . json_encode($notifyData,JSON_UNESCAPED_UNICODE));

                // 查询订单
                $GoodsOrderModel =  new \app\common\model\WmbOrder();
                $order = $GoodsOrderModel->where('order_no', $out_trade_no)->find();
                if (!$order || $order['status'] != 0) {
                    Log::info('订单不存在或者已经支付了');
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                
                elseif($notifyData['trade_state'] === 'SUCCESS'){
                    $order->out_trade_no = $notifyData['transaction_id'];
                    $order->pay_time = $success_time;
                    $order->status = 1;
                    $order->save();
                    $r = $GoodsOrderModel->deliverCreate($out_trade_no);
                    @Log::info('聚合外卖发起配送' . json_encode($r,JSON_UNESCAPED_UNICODE));
                }

                elseif ($message['result_code'] === 'FAIL') {
                    // 支付失败逻辑
                    return ['code' => 'ERROR', 'message' => '支付失败'];
                }

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }
    
    
       //余额充值支付通知
    public function notifyvip()
    {
        Log::info('会员卡支付调来了');
        try {
            //log::info();
            $app    = new Application([
                'mch_id'      => $this->wechatPayConfig['mch_id'],
                'secret_key'  => $this->wechatPayConfig['secret_key'],
                'certificate' => root_path() . $this->wechatPayConfig['certificate'],
                'private_key' => root_path() . $this->wechatPayConfig['private_key'],
                'notify_url'  => $this->wechatPayConfig['notify_url'],
                'http'        => [
                    'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
                    'timeout' => 5.0,
                ],
            ]);
            $server = $app->getServer();
            $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
                $notifyData   = json_decode($message, true);
                $success_time = strtotime($notifyData['success_time']);
                $out_trade_no = $notifyData['out_trade_no'];
                 
                Log::info('会员卡支付回调来了' . json_encode($notifyData,JSON_UNESCAPED_UNICODE));
                $data = explode('S',$out_trade_no);
                // 查询订单
                $order = Db::name('user_vip')->where('order_id', $out_trade_no)->find();
                if ($order) {
                    Log::info('订单已经支付了');
                    return ['code' => 'SUCCESS', 'message' => '成功'];
                }
                
                elseif($notifyData['trade_state'] === 'SUCCESS'){
                    $res = $log->change($data[0],3,($data[1]/100),$out_trade_no,'','',2);
                    $log = [
                      'user_id' => $data[0],
                      'user_level_id' => $data[1],
                      'price' => $data[2],
                      'create_time' => time(),
                      'order_id' => $out_trade_no
                    ];
                    Db::name('user_vip')->insert($log);
                    Db::name('user')->where('id', $data[0])->update(['level'=>$data[1]]);
                    Log::info('会员卡充值' . json_encode($res,320));
                }

                elseif ($message['result_code'] === 'FAIL') {
                    // 支付失败逻辑
                    return ['code' => 'ERROR', 'message' => '支付失败'];
                }

                return $next($message);
            });
            return $server->serve();
        } catch (InvalidArgumentException|RuntimeException|\ReflectionException|\Throwable $e) {
            $this->error($e->getMessage());
            file_put_contents('pay_error.txt',$e->getMessage() . PHP_EOL, FILE_APPEND);
        }
    }

}